Kurt Hsu's blog

The Rails developer in taiwan.


  • 首頁

  • 標籤

  • 分類

  • 歸檔

[Rails]基本Routes設計

發表於 2018-07-20 更新於 2019-09-07 分類於 Rails , Routes

在之前文章[Rails]簡單的掌握Routes, Rails在基本的resources使用上已經非常方便, 但在工作上第一次遇到shallow等用法的時候即使rake routes出來仍然一頭霧水為什麼會出現這樣的結果, 所以記錄一下自己研究後的觀念

此篇目的

  1. 理解Routes邏輯
  2. 嵌套資源(Nested resources)
  3. 認識shallow
  4. 認識namespace
  5. 漂亮的客製化例如 admin/posts/generator 這種route

理解Routes邏輯

先以最基本的resources :posts當範例

1
2
3
Rails.application.routes.draw do
resources :posts
end

$ rake routes得到的結果

Prefix Verb URI Pattern Controller#Action
posts GET /posts(.:format) posts#index
POST /posts(.:format) posts#create
new_post GET /posts/new(.:format) posts#new
edit_post GET /posts/:id/edit(.:format) posts#edit
post GET /posts/:id(.:format) posts#show
PATCH /posts/:id(.:format) posts#update
PUT /posts/:id(.:format) posts#update
DELETE /posts/:id(.:format) posts#destroy

Prefix

Prefix加上_path就是Rails的Route helper, 例如想要連去Post index就在view寫上
<%= link_to posts_path %>

再來如果看到Prefix為空, 例如如上表create動作Prefix為就空, 就代表Prefix與上一個相同, 但要注意Verb是什麼, link_to預設都是GET, 所以要連去create post view則寫
<%= link_to posts_path, method: :post %>

URI Pattern

URI Pattern就是網址, 前面就是自己的網域, (.:format)就是要render的格式, 可以是html, JSON等等在controller設定即可就不探討, 預設是html, 之後的表單就省略不寫(.:format)了

再來可以注意到像show的網址有:id這個參數, 就得帶想要看的id進去, 所以要連去第1篇post view則寫
<%= link_to post_path(1) %>

帶一個物件也可以, 我們很常在controller看到

1
2
post = Post.find(1)
redirect_to post_path(post)

Controller#Action

顧名思義就是找哪個controller的哪個action, 如果有namespace則要注意資料夾結構, 檔案要放對位置

嵌套資源(Nested resources)

在post下嵌套comment當範例

1
2
3
4
5
Rails.application.routes.draw do
resources :posts do
resources :comments
end
end

$ rake routes | grep comments我們先只看comment的結果

Prefix Verb URI Pattern Controller#Action
post_comments_index GET /posts/:post_id/comments comments#index
POST /posts/:post_id/comments comments#create
new_post_comments GET /posts/:post_id/comments/new comments#new
edit_post_comments GET /posts/:post_id/comments/:id/edit comments#edit
post_comments GET /posts/:post_id/comments/:id comments#show
PATCH /posts/:post_id/comments/:id comments#update
PUT /posts/:post_id/comments/:id comments#update
DELETE /posts/:post_id/comments/:id comments#destroy

照著上一個例子的邏輯沒什麼太大的問題, 唯一要注意的是較好的設計規範
嵌套資源不要超過一層
例如這個例子就是有一層了, 盡量不要再往下有resources, 難維護也比較沒意義

認識shallow

先理解shallow的設計邏輯:

  1. 只有該文章可以列出自己所有的comment, 並且new和create
  2. 在任何地方只要能找到該comment就可以show, edit, update, destroy他

只要簡單的寫一行即可做到這個邏輯

1
2
3
resources :posts do
resources :comments, shallow: true
end

其效果等同於

1
2
3
4
resources :posts do
resources :comments, only: [:index, :new, :create]
end
resources :comments, only: [:show, :edit, :update, :destroy]

或者這樣比較看得懂

1
2
3
4
resources :posts do
resources :comments, except: [:show, :edit, :update, :destroy]
end
resources :comments, only: [:show, :edit, :update, :destroy]

再來根據前面的例子試著$ rake routes結果吧!

認識namespace

最常使用的地方是後台的建構, 例如:

1
2
3
namespace :admin do
resources :posts
end

$ rake routes會發現所有東西都加上了admin

Prefix Verb URI Pattern Controller#Action
admin_posts GET /admin/posts admin/posts#index
POST /admin/posts admin/posts#create
new_admin_post GET /admin/posts/new admin/posts#new
edit_admin_post GET /admin/posts/:id/edit admin/posts#edit
admin_post GET /admin/posts/:id admin/posts#show
PATCH /admin/posts/:id admin/posts#update
PUT /admin/posts/:id admin/posts#update
DELETE /admin/posts/:id admin/posts#destroy

比較要注意的是Controller#Action的部分, 此時的controller要放在
app/controllers/admin/posts_controller.rb
而檔案裡面class name要改為

1
2
class Admin::PostsController
end

漂亮的客製化例如 admin/posts/generator 這種route

利用collection可以蠻方便客製化出想要的route, 但post複數以及單數兩種情況, 如果是複數的話利用即可

1
2
3
4
5
6
7
namespace :admin do
resource :posts do
collection do
get 'generator'
end
end
end

$ rake routes | grep generator結果如下:

Prefix Verb URI Pattern Controller#Action
generator_admin_posts GET /admin/posts/generator admin/posts#generator

即可快速的創造好複數的route, 但對於覺得generator應該是單數的post的人認為Prefix就會不ok, 比較簡單的單數解法就如下:

1
2
3
4
5
6
7
8
namespace :admin do
resource :posts
resource :post do
collection do
get 'generator'
end
end
end

簡化一點點:

1
2
3
4
5
6
namespace :admin do
resource :posts
resource :post do
get 'generator', on: :collection
end
end

$ rake routes | grep generator結果如下:

Prefix Verb URI Pattern Controller#Action
generator_admin_post GET /admin/post/generator admin/post#generator

比較要注意的是Controller#Action要的controller是單數的
app/controllers/admin/post_controller.rb

小結

當然routes還有很多寫法, 也很容易hack, 利如又想單數又想直接共用複數的controller也可以這樣寫:

1
2
3
4
5
6
namespace :admin do
resource :posts
resource :post do
get 'generator', on: :collection, to: 'admin/posts#generator'
end
end

甚至直接一行幹到底:

1
get 'admin/post/generator', to: 'admin/posts#generator', as: 'generator_admin_post'

不管想怎麼寫, 保持不斷的rake route查明結果吧!!

參考文章:
書籍 - 為你自己學Ruby on Rails2017.09初版
Rails 路由:深入淺出

# Rails # Routes
[Rails] I18n 基本使用
[生活]從前端轉戰Rails後成為T客邦的一份子
  • 文章目錄
  • 本站概要

Kurt Hsu

Progress One Percent Every Day
171 文章
55 分類
163 標籤
RSS
  1. 1. 此篇目的
  2. 2. 理解Routes邏輯
    1. 2.0.1. Prefix
    2. 2.0.2. URI Pattern
    3. 2.0.3. Controller#Action
  • 3. 嵌套資源(Nested resources)
  • 4. 認識shallow
  • 5. 認識namespace
  • 6. 漂亮的客製化例如 admin/posts/generator 這種route
  • 7. 小結
  • © 2020 Kurt Hsu
    由 Hexo 強力驅動 v3.8.0
    |
    主題 – NexT.Muse v7.3.0